// 版权所有2009年围棋作者。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

// 删除要包含在gob包中的下一行。
// go:构建忽略
// +构建忽略

package gob

// 此文件通常不包含在gob包中。仅用于调试包本身。
// 除了读取uint之外，它是独立于uint的读取器的实现
// 由译码器实现的。
// 要启用调试功能，请删除上面的+build ignore行并执行以下操作
// 去安装

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"strings"
	"sync"
)

var dumpBytes = false // 如果为true，则在每个项目处打印输入缓冲区中的剩余字节。

// Init安装调试工具。如果此文件未在
// 包中，codec_test.go中的测试不是ops。
func init() {
	debugFunc = Debug
}

var (
	blanks = bytes.Repeat([]byte{' '}, 3*10)
	empty  = []byte(": <empty>\n")
	tabs   = strings.Repeat("\t", 100)
)

// 制表符在打印时会自动缩进。
type tab int

func (t tab) String() string {
	n := int(t)
	if n > len(tabs) {
		n = len(tabs)
	}
	return tabs[0:n]
}

func (t tab) print() {
	fmt.Fprint(os.Stderr, t)
}

// peekReader包装了一个io.Reader，允许一个人向前看
// 没有从读者的客户端窃取数据的情况下会发生什么。
type peekReader struct {
	r    io.Reader
	data []byte // 预读数据
}

// newPeekReader返回一个包装r的peekReader。
func newPeekReader(r io.Reader) *peekReader {
	return &peekReader{r: r}
}

// 阅读是常用的方法。它将首先获取预先读取的数据。
func (p *peekReader) Read(b []byte) (n int, err error) {
	if len(p.data) == 0 {
		return p.r.Read(b)
	}
	// 满足预读数据的可能要求。
	n = copy(b, p.data)
	// 将数据向下移动到切片的开头，以避免无休止的增长
	copy(p.data, p.data[n:])
	p.data = p.data[:len(p.data)-n]
	return
}

// peek从未读文件返回尽可能多的字节
// 流的一部分，最大长度为b。
func (p *peekReader) peek(b []byte) (n int, err error) {
	if len(p.data) > 0 {
		n = copy(b, p.data)
		if n == len(b) {
			return
		}
		b = b[n:]
	}
	if len(b) == 0 {
		return
	}
	m, e := io.ReadFull(p.r, b)
	if m > 0 {
		p.data = append(p.data, b[:m]...)
	}
	n += m
	if e == io.ErrUnexpectedEOF {
		// 这意味着m>0，但我们达到了EOF。如果我们有数据
		// 我们不会抱怨看得不够多。
		if n > 0 {
			e = nil
		} else {
			e = io.EOF
		}
	}
	return n, e
}

type debugger struct {
	mutex          sync.Mutex
	remain         int  // 输入中已知保留的字节数
	remainingKnown bool // “保留”的值有效
	r              *peekReader
	wireType       map[typeId]*wireType
	tmp            []byte // 用于解码单元的暂存空间。
}

// 转储打印下一个N字节的输入。
// 它安排打印从调用到的对齐输出
// 呼叫，以便轻松查看已消耗的内容。
func (deb *debugger) dump(format string, args ...interface{}) {
	if !dumpBytes {
		return
	}
	fmt.Fprintf(os.Stderr, format+" ", args...)
	if !deb.remainingKnown {
		return
	}
	if deb.remain < 0 {
		fmt.Fprintf(os.Stderr, "remaining byte count is negative! %d\n", deb.remain)
		return
	}
	data := make([]byte, deb.remain)
	n, _ := deb.r.peek(data)
	if n == 0 {
		os.Stderr.Write(empty)
		return
	}
	b := new(bytes.Buffer)
	fmt.Fprintf(b, "[%d]{\n", deb.remain)
	// 空白直到第一个字节
	lineLength := 0
	if n := len(data); n%10 != 0 {
		lineLength = 10 - n%10
		fmt.Fprintf(b, "\t%s", blanks[:lineLength*3])
	}
	// 每行10字节
	for len(data) > 0 {
		if lineLength == 0 {
			fmt.Fprint(b, "\t")
		}
		m := 10 - lineLength
		lineLength = 0
		if m > len(data) {
			m = len(data)
		}
		fmt.Fprintf(b, "% x\n", data[:m])
		data = data[m:]
	}
	fmt.Fprint(b, "}\n")
	os.Stderr.Write(b.Bytes())
}

// Debug打印从r读取的gob数据的可读表示形式。
// 除非在生成包时启用了调试，否则它是不可操作的。
func Debug(r io.Reader) {
	err := debug(r)
	if err != nil {
		fmt.Fprintf(os.Stderr, "gob debug: %s\n", err)
	}
}

// debug实现debug，但捕获恐慌并返回
// 它们将作为错误由调试打印。
func debug(r io.Reader) (err error) {
	defer catchError(&err)
	fmt.Fprintln(os.Stderr, "Start of debugging")
	deb := &debugger{
		r:        newPeekReader(r),
		wireType: make(map[typeId]*wireType),
		tmp:      make([]byte, 16),
	}
	if b, ok := r.(*bytes.Buffer); ok {
		deb.remain = b.Len()
		deb.remainingKnown = true
	}
	deb.gobStream()
	return
}

// 注意，我们已经消耗了一些字节
func (deb *debugger) consumed(n int) {
	if deb.remainingKnown {
		deb.remain -= n
	}
}

// int64解码并返回下一个整数，该整数必须存在。
// 如果你能在EOF，就别打这个电话。
func (deb *debugger) int64() int64 {
	return toInt(deb.uint64())
}

// uint64返回并解码必须存在的下一个无符号整数。
// 如果你能在EOF，就别打这个电话。
// TODO:更好地处理错误。
func (deb *debugger) uint64() uint64 {
	n, w, err := decodeUintReader(deb.r, deb.tmp)
	if err != nil {
		errorf("debug: read error: %s", err)
	}
	deb.consumed(w)
	return n
}

// GobStream：
// DelimitedMessage*（直到EOF）
func (deb *debugger) gobStream() {
	// 确保我们在这里是单线程的。
	deb.mutex.Lock()
	defer deb.mutex.Unlock()

	for deb.delimitedMessage(0) {
	}
}

// 分隔消息：
// uint（长消息）消息
func (deb *debugger) delimitedMessage(indent tab) bool {
	for {
		n := deb.loadBlock(true)
		if n < 0 {
			return false
		}
		deb.dump("Delimited message of length %d", n)
		deb.message(indent)
	}
	return true
}

// loadBlock使我们能够阅读消息
// 输入中下一个指定的长度。它回来了
// 块的长度。这个论点说明
// EOF现在是可以接受的。如果是的，并且找到了一个，
// 返回值为负。
func (deb *debugger) loadBlock(eofOK bool) int {
	n64, w, err := decodeUintReader(deb.r, deb.tmp) // deb.uint64将在EOF时出错
	if err != nil {
		if eofOK && err == io.EOF {
			return -1
		}
		errorf("debug: unexpected error: %s", err)
	}
	deb.consumed(w)
	n := int(n64)
	if n < 0 {
		errorf("huge value for message length: %d", n64)
	}
	return int(n)
}

// 信息：
// 类型序列类型值
// 类型序列
// （TypeDefinition DelimitedTypeDefinition*）？
// 分隔类型定义：
// uint（长度类型定义）类型定义
// 类型值：
// int（typeId）值
func (deb *debugger) message(indent tab) bool {
	for {
		// 将uint64转换为有符号整数类型ID
		uid := deb.int64()
		id := typeId(uid)
		deb.dump("type id=%d", id)
		if id < 0 {
			deb.typeDefinition(indent, -id)
			n := deb.loadBlock(false)
			deb.dump("Message of length %d", n)
			continue
		} else {
			deb.value(indent, id)
			break
		}
	}
	return true
}

// 帮助器方法使扫描类型描述符变得容易。

// common返回输入点处的CommonType。
func (deb *debugger) common() CommonType {
	fieldNum := -1
	name := ""
	id := typeId(0)
	for {
		delta := deb.delta(-1)
		if delta == 0 {
			break
		}
		fieldNum += delta
		switch fieldNum {
		case 0:
			name = deb.string()
		case 1:
			// Id类型Id
			id = deb.typeId()
		default:
			errorf("corrupted CommonType, delta is %d fieldNum is %d", delta, fieldNum)
		}
	}
	return CommonType{name, id}
}

// uint以uint（不是uint64）的形式返回输入点处的无符号int。
func (deb *debugger) uint() uint {
	return uint(deb.uint64())
}

// int以int（而不是int64）的形式返回输入点处有符号的int。
func (deb *debugger) int() int {
	return int(deb.int64())
}

// typeId返回输入点的类型id。
func (deb *debugger) typeId() typeId {
	return typeId(deb.int64())
}

// string返回输入点处的字符串。
func (deb *debugger) string() string {
	x := int(deb.uint64())
	b := make([]byte, x)
	nb, _ := deb.r.Read(b)
	if nb != x {
		errorf("corrupted type")
	}
	deb.consumed(nb)
	return string(b)
}

// delta返回输入点处的字段delta。expect参数，
// 如果为非负，则标识值应该是什么。
func (deb *debugger) delta(expect int) int {
	delta := int(deb.uint64())
	if delta < 0 || (expect >= 0 && delta != expect) {
		errorf("decode: corrupted type: delta %d expected %d", delta, expect)
	}
	return delta
}

// 类型定义：
// [int（-typeId）（已读）]编码WireType
func (deb *debugger) typeDefinition(indent tab, id typeId) {
	deb.dump("type definition for id %d", id)
	// 编码是有线类型的。像往常一样解码结构
	fieldNum := -1
	wire := new(wireType)
	// 线类型定义单个字段。
	delta := deb.delta(-1)
	fieldNum += delta
	switch fieldNum {
	case 0: // 数组类型，一个{Common}，elem，length}字段
		// 字段号0为CommonType
		deb.delta(1)
		com := deb.common()
		// 字段编号1是元素的类型Id
		deb.delta(1)
		id := deb.typeId()
		// 字段3是长度
		deb.delta(1)
		length := deb.int()
		wire.ArrayT = &arrayType{com, id, length}

	case 1: // 切片类型，{{Common}，elem}的一个字段
		// 字段号0为CommonType
		deb.delta(1)
		com := deb.common()
		// 字段编号1是元素的类型Id
		deb.delta(1)
		id := deb.typeId()
		wire.SliceT = &sliceType{com, id}

	case 2: // 结构类型，一个{{Common}，[]fieldType}字段
		// 字段号0为CommonType
		deb.delta(1)
		com := deb.common()
		// 字段编号1是FieldType的切片
		deb.delta(1)
		numField := int(deb.uint())
		field := make([]*fieldType, numField)
		for i := 0; i < numField; i++ {
			field[i] = new(fieldType)
			deb.delta(1) // fieldType的字段0:名称
			field[i].Name = deb.string()
			deb.delta(1) // fieldType的字段1：id
			field[i].Id = deb.typeId()
			deb.delta(0) // 字段结束类型
		}
		wire.StructT = &structType{com, field}

	case 3: // 映射类型，一个{{Common}字段，key，elem}
		// 字段号0为CommonType
		deb.delta(1)
		com := deb.common()
		// 字段编号1是密钥的类型Id
		deb.delta(1)
		keyId := deb.typeId()
		// 字段编号2是元素的类型Id
		deb.delta(1)
		elemId := deb.typeId()
		wire.MapT = &mapType{com, keyId, elemId}
	case 4: // GobEncoder类型，一个{{Common}字段
		// 字段号0为CommonType
		deb.delta(1)
		com := deb.common()
		wire.GobEncoderT = &gobEncoderType{com}
	case 5: // BinaryMarshaler类型，一个{{Common}字段
		// 字段号0为CommonType
		deb.delta(1)
		com := deb.common()
		wire.BinaryMarshalerT = &gobEncoderType{com}
	case 6: // TextMarshaler类型，一个{{Common}字段
		// 字段号0为CommonType
		deb.delta(1)
		com := deb.common()
		wire.TextMarshalerT = &gobEncoderType{com}
	default:
		errorf("bad field in type %d", fieldNum)
	}
	deb.printWireType(indent, wire)
	deb.delta(0) // 端部内部类型（阵列类型等）
	deb.delta(0) // 端部线型
	// 记住我们见过这种类型。
	deb.wireType[id] = wire
}

// 价值：
// SingletonValue | StructValue
func (deb *debugger) value(indent tab, id typeId) {
	wire, ok := deb.wireType[id]
	if ok && wire.StructT != nil {
		deb.structValue(indent, id)
	} else {
		deb.singletonValue(indent, id)
	}
}

// 单音值：
// uint（0）字段值
func (deb *debugger) singletonValue(indent tab, id typeId) {
	deb.dump("Singleton value")
	// 是内置式的吗？
	wire := deb.wireType[id]
	_, ok := builtinIdToType[id]
	if !ok && wire == nil {
		errorf("type id %d not defined", id)
	}
	m := deb.uint64()
	if m != 0 {
		errorf("expected zero; got %d", m)
	}
	deb.fieldValue(indent, id)
}

// 界面价值：
// NilInterfaceValue |非NilInterfaceValue
func (deb *debugger) interfaceValue(indent tab) {
	deb.dump("Start of interface value")
	if nameLen := deb.uint64(); nameLen == 0 {
		deb.nilInterfaceValue(indent)
	} else {
		deb.nonNilInterfaceValue(indent, int(nameLen))
	}
}

// 无接口评估值：
// uint（0）[已读]
func (deb *debugger) nilInterfaceValue(indent tab) int {
	fmt.Fprintf(os.Stderr, "%snil interface\n", indent)
	return 0
}

// 非零接口值：
// ConcreteTypeName类型序列接口内容
// 具体类型名称：
// uint（lengthOfName）[已读=n]名称
// 接口内容：
// int（concreteTypeId）分隔值
// 分隔值：
// uint（长度）值
func (deb *debugger) nonNilInterfaceValue(indent tab, nameLen int) {
	// 具体类型名称
	b := make([]byte, nameLen)
	deb.r.Read(b) // TODO:检查这些读数！！
	deb.consumed(nameLen)
	name := string(b)

	for {
		id := deb.typeId()
		if id < 0 {
			deb.typeDefinition(indent, -id)
			n := deb.loadBlock(false)
			deb.dump("Nested message of length %d", n)
		} else {
			// 定界值
			x := deb.uint64() // 如果我们想忽略这个值；我们没有。
			fmt.Fprintf(os.Stderr, "%sinterface value, type %q id=%d; valueLength %d\n", indent, name, id, x)
			deb.value(indent, id)
			break
		}
	}
}

// printCommonType打印公共类型；由printWireType使用。
func (deb *debugger) printCommonType(indent tab, kind string, common *CommonType) {
	indent.print()
	fmt.Fprintf(os.Stderr, "%s %q id=%d\n", kind, common.Name, common.Id)
}

// printWireType打印wireType的内容。
func (deb *debugger) printWireType(indent tab, wire *wireType) {
	fmt.Fprintf(os.Stderr, "%stype definition {\n", indent)
	indent++
	switch {
	case wire.ArrayT != nil:
		deb.printCommonType(indent, "array", &wire.ArrayT.CommonType)
		fmt.Fprintf(os.Stderr, "%slen %d\n", indent+1, wire.ArrayT.Len)
		fmt.Fprintf(os.Stderr, "%selemid %d\n", indent+1, wire.ArrayT.Elem)
	case wire.MapT != nil:
		deb.printCommonType(indent, "map", &wire.MapT.CommonType)
		fmt.Fprintf(os.Stderr, "%skey id=%d\n", indent+1, wire.MapT.Key)
		fmt.Fprintf(os.Stderr, "%selem id=%d\n", indent+1, wire.MapT.Elem)
	case wire.SliceT != nil:
		deb.printCommonType(indent, "slice", &wire.SliceT.CommonType)
		fmt.Fprintf(os.Stderr, "%selem id=%d\n", indent+1, wire.SliceT.Elem)
	case wire.StructT != nil:
		deb.printCommonType(indent, "struct", &wire.StructT.CommonType)
		for i, field := range wire.StructT.Field {
			fmt.Fprintf(os.Stderr, "%sfield %d:\t%s\tid=%d\n", indent+1, i, field.Name, field.Id)
		}
	case wire.GobEncoderT != nil:
		deb.printCommonType(indent, "GobEncoder", &wire.GobEncoderT.CommonType)
	}
	indent--
	fmt.Fprintf(os.Stderr, "%s}\n", indent)
}

// fieldValue打印任何类型的值，例如结构字段。
// 字段值：
// 内置值|数组值|映射值|切片值|结构值|接口值
func (deb *debugger) fieldValue(indent tab, id typeId) {
	_, ok := builtinIdToType[id]
	if ok {
		if id == tInterface {
			deb.interfaceValue(indent)
		} else {
			deb.printBuiltin(indent, id)
		}
		return
	}
	wire, ok := deb.wireType[id]
	if !ok {
		errorf("type id %d not defined", id)
	}
	switch {
	case wire.ArrayT != nil:
		deb.arrayValue(indent, wire)
	case wire.MapT != nil:
		deb.mapValue(indent, wire)
	case wire.SliceT != nil:
		deb.sliceValue(indent, wire)
	case wire.StructT != nil:
		deb.structValue(indent, id)
	case wire.GobEncoderT != nil:
		deb.gobEncoderValue(indent, id)
	default:
		panic("bad wire type for field")
	}
}

// printBuiltin打印的值不是基本类型，即，
// 在引导时已知其类型为GOB的人。
func (deb *debugger) printBuiltin(indent tab, id typeId) {
	switch id {
	case tBool:
		x := deb.int64()
		if x == 0 {
			fmt.Fprintf(os.Stderr, "%sfalse\n", indent)
		} else {
			fmt.Fprintf(os.Stderr, "%strue\n", indent)
		}
	case tInt:
		x := deb.int64()
		fmt.Fprintf(os.Stderr, "%s%d\n", indent, x)
	case tUint:
		x := deb.uint64()
		fmt.Fprintf(os.Stderr, "%s%d\n", indent, x)
	case tFloat:
		x := deb.uint64()
		fmt.Fprintf(os.Stderr, "%s%g\n", indent, float64FromBits(x))
	case tComplex:
		r := deb.uint64()
		i := deb.uint64()
		fmt.Fprintf(os.Stderr, "%s%g+%gi\n", indent, float64FromBits(r), float64FromBits(i))
	case tBytes:
		x := int(deb.uint64())
		b := make([]byte, x)
		deb.r.Read(b)
		deb.consumed(x)
		fmt.Fprintf(os.Stderr, "%s{% x}=%q\n", indent, b, b)
	case tString:
		x := int(deb.uint64())
		b := make([]byte, x)
		deb.r.Read(b)
		deb.consumed(x)
		fmt.Fprintf(os.Stderr, "%s%q\n", indent, b)
	default:
		panic("unknown builtin")
	}
}

// 数组值：
// uint（n）字段值*n
func (deb *debugger) arrayValue(indent tab, wire *wireType) {
	elemId := wire.ArrayT.Elem
	u := deb.uint64()
	length := int(u)
	for i := 0; i < length; i++ {
		deb.fieldValue(indent, elemId)
	}
	if length != wire.ArrayT.Len {
		fmt.Fprintf(os.Stderr, "%s(wrong length for array: %d should be %d)\n", indent, length, wire.ArrayT.Len)
	}
}

// 映射值：
// uint（n）（字段值字段值）*n[n（键、值）对]
func (deb *debugger) mapValue(indent tab, wire *wireType) {
	keyId := wire.MapT.Key
	elemId := wire.MapT.Elem
	u := deb.uint64()
	length := int(u)
	for i := 0; i < length; i++ {
		deb.fieldValue(indent+1, keyId)
		deb.fieldValue(indent+1, elemId)
	}
}

// 切片值：
// uint（n）（n字段值）
func (deb *debugger) sliceValue(indent tab, wire *wireType) {
	elemId := wire.SliceT.Elem
	u := deb.uint64()
	length := int(u)
	deb.dump("Start of slice of length %d", length)

	for i := 0; i < length; i++ {
		deb.fieldValue(indent, elemId)
	}
}

// 结构值：
// （uint（fieldDelta）FieldValue）*
func (deb *debugger) structValue(indent tab, id typeId) {
	deb.dump("Start of struct value of %q id=%d\n<<\n", id.name(), id)
	fmt.Fprintf(os.Stderr, "%s%s struct {\n", indent, id.name())
	wire, ok := deb.wireType[id]
	if !ok {
		errorf("type id %d not defined", id)
	}
	strct := wire.StructT
	fieldNum := -1
	indent++
	for {
		delta := deb.uint64()
		if delta == 0 { // 结构终止符为零delta fieldnum
			break
		}
		fieldNum += int(delta)
		if fieldNum < 0 || fieldNum >= len(strct.Field) {
			deb.dump("field number out of range: prevField=%d delta=%d", fieldNum-int(delta), delta)
			break
		}
		fmt.Fprintf(os.Stderr, "%sfield %d:\t%s\n", indent, fieldNum, wire.StructT.Field[fieldNum].Name)
		deb.fieldValue(indent+1, strct.Field[fieldNum].Id)
	}
	indent--
	fmt.Fprintf(os.Stderr, "%s} // 结束%s结构\n“，缩进，id.name（））
	deb.dump(">> End of struct value of type %d %q", id, id.name())
}

// GobEncoderValue：
// uint（n）字节*n
func (deb *debugger) gobEncoderValue(indent tab, id typeId) {
	len := deb.uint64()
	deb.dump("GobEncoder value of %q id=%d, length %d\n", id.name(), id, len)
	fmt.Fprintf(os.Stderr, "%s%s (implements GobEncoder)\n", indent, id.name())
	data := make([]byte, len)
	_, err := deb.r.Read(data)
	if err != nil {
		errorf("gobEncoder data read: %s", err)
	}
	fmt.Fprintf(os.Stderr, "%s[% .2x]\n", indent+1, data)
}
